import * as Babel from '@babel/standalone';

export async function processHtmlString(html: string) {
  //必须有template
  let match = html.match(/<template.*>((?:.|\r|\n|\t)*)<\/template>/)
  if(!match){
    console.error(html);
    console.error('解析 template 失败！');
    return null;
  }
  const template = match[1];

  //可以没有script
  let script = '';
  if (html.indexOf('<script') > -1) {
    match = html.match(/<script.*>((?:.|\r|\n|\t)*)<\/script>/)
    if (!match) {
      console.error(html)
      console.error('解析 script 失败！')
      return null
    }
    script = match[1].trim()
  }

  //可以没有style
  match = html.match(/<style.*>((?:.|\r|\n|\t)*)<\/style>/)
  let style = !!match ? match[1] : null

  return {
    template,
    script: !!script ? await processScriptString(script) : {},
    style,
  }
}

async function processScriptString(scriptString: string) {
  //@ts-ignore
  const output = Babel.transform(scriptString,{
    presets: [
      'env'
    ]
  }).code as string;

  const require = await buildDependency(output);
  const fn = new Function('module,exports,require', output);
  const module = {exports: {} as any,};
  fn.call(module, module, module.exports, require); //<script>里的代码此时执行
  return module.exports.default;
}

async function buildDependency(output: string) {

  let names: string[] = []
  const regexp = /require\('(.*)'\)/g
  let match = regexp.exec(output)
  while (!!match) {
    names.push(match[1])
    match = regexp.exec(output)
  }
  const dependencies = (await Promise.all(names.map(async name => {
    if (name === 'vue') return {
      name,
      module: await import('vue'),
    }
    if (name === 'element-ui-plus') return {
      name,
      // module: await import('element-ui-plus/src/index')
    }
    const msg = `没有安装依赖：${name}`
    console.warn(msg)
    throw new Error(msg)
  }))).reduce((prev, {name, module}) => {
    prev[name] = module
    return prev
  }, {} as Record<string, any>)

  return (name: string) => {
    return dependencies[name]
  }
}
